﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Idenmpotency;
using Microsoft.Extensions.DependencyInjection;
using Yarp.ReverseProxy.Model;

namespace Yarp.ReverseProxy.Idenmptency
{
    /// <summary>
    /// 内置的请求工厂
    ///这个类的主要目的是进行对幂等请求创建过程的装饰，
    ///添加Yarp特性，例如使用Yarp配置来进行标识
    ///使用配置来定义哪一个路由需要幂等性验证
    /// </summary>
    internal class YarpIdenmpotencyRequestFactory : IAspIdenmpotencyRequestFactory
    {
        /// <summary>
        /// 生成器
        /// </summary>
        IYarpIdenmpotencyRequestGenerator _generator;

        /// <summary>
        /// 请求工厂
        /// </summary>
        /// <param name="generator"></param>
        public YarpIdenmpotencyRequestFactory(IYarpIdenmpotencyRequestGenerator generator)
        {
            this._generator = generator;
        }

        /// <summary>
        /// 创建Asp幂等性请求
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public IAspIdenmpotencyRequest Create(HttpContext context, RequestDelegate next)
        {
            //获取幂等请求
            var request= _generator.Generate(context, next);
            var result = false;
            {
                var endpoint = context.GetEndpoint()
                ?? throw new InvalidOperationException($"Routing Endpoint wasn't set for the current request.");

                var route = endpoint.Metadata.GetMetadata<RouteModel>()
                    ?? throw new InvalidOperationException($"Routing Endpoint is missing {typeof(RouteModel).FullName} metadata.");

                var routeId = route.Config.RouteId;

                var repository=context.RequestServices.GetService<IYarpRouteIdenmpotencyRepository>();

                result = repository.IsIdenmpotencyRoute(routeId);
            }
            //如果幂等
            if (result) return new YarpIdenmpotencyRequest(context, next, request.Key);
            else return null;
        }
    }

}
